 package parser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * @author greg
 * Represents a set of strings and the match locations
 * associated with them
 */
public class StringMatchSet {
	//private HashMap<String,Set<StringMatch>> list;
	public HashSet<StringMatch> matchSet;
	//public HashSet<StringMatch> matchList;
	public StringMatchSet() {
		//list = new HashMap<String,Set<StringMatch>>();
		matchSet = new HashSet<StringMatch>();
	}
	
	public StringMatchSet(HashSet<StringMatch> matchSet) {
		//list = new HashMap<String,Set<StringMatch>>();
		this.matchSet = matchSet;
	}
	
	
	
	/**
	 * Copy constructor
	 * @param o StringMatchList to clone
	 */
	@SuppressWarnings("unchecked")
	public StringMatchSet(StringMatchSet o) {
		matchSet = (HashSet<StringMatch>) o.matchSet.clone();
	}
	
	public int size() {
		return matchSet.size();
	}
	
	// set operations
	/*private static Set<StringMatch> unionHashSet(Set<StringMatch> hs1, Set<StringMatch> hs2) {
		Set<StringMatch> union = (HashSet<StringMatch>) ((HashSet<StringMatch>)hs1).clone();
		Set<StringMatch> union2 = (HashSet<StringMatch>) ((HashSet<StringMatch>)hs2).clone();
		union.addAll(union2);
		return union;
	}*/
	/*public static StringMatchSet union(StringMatchSet l1, StringMatchSet l2) {
		StringMatchSet union = new StringMatchSet(l1);
		for(String key : l2.getStrings()) {
			if(union.containsString(key)) {
				Set<StringMatch> stringMatchesUnion = unionHashSet(union.get(key),l2.get(key));
				union.putSet(key, stringMatchesUnion);		
			} else {
				union.putSet(key, l2.get(key));
			}
		}
		
		return union;
	}*/
	public static StringMatchSet union(StringMatchSet l1, StringMatchSet l2) {
		HashSet<StringMatch> union = new HashSet<StringMatch>();
		union.addAll(l1.matchSet);
		union.addAll(l2.matchSet);
		
		StringMatchSet retval = new StringMatchSet(union);
		
		return retval;
	}
	public StringMatchSet union(StringMatchSet o) {
		return StringMatchSet.union(this, o);
	}
	
	public static StringMatchSet intersection(StringMatchSet l1, StringMatchSet l2) {
		
		
		StringMatchSet inters = new StringMatchSet();
		
		HashSet<String> l1Set = new HashSet<String>();
		HashSet<String> l2Set = new HashSet<String>();
		HashSet<StringMatch> resultSet = new HashSet<StringMatch>();
		
		for(StringMatch sm:l1.matchSet)
		{
			l1Set.add(sm.value);
		}
		for(StringMatch sm:l2.matchSet)
		{
			l2Set.add(sm.value);
		}
		l1Set.retainAll(l2Set);
		for(StringMatch sm:l1.matchSet)
		{
				if(l1Set.contains(sm.value))
					resultSet.add(sm);
		}
		for(StringMatch sm:l2.matchSet)
		{
				if(l1Set.contains(sm.value))
					resultSet.add(sm);
		}
		inters.matchSet = resultSet;
		/*for(String key : l2.getStrings()) {
			if(l1.containsString(key) && l2.containsString(key)) {
				inters.putSet(key, unionHashSet(l1.get(key),l2.get(key)));
			}
		}*/
		
		return inters;
	}
	
	public StringMatchSet intersection(StringMatchSet o) {
		return StringMatchSet.intersection(this, o);
	}
	
	public static StringMatchSet difference(StringMatchSet l1, StringMatchSet l2) {
		StringMatchSet diff = new StringMatchSet();

		
		HashSet<String> l1Set = new HashSet<String>();
		HashSet<String> l2Set = new HashSet<String>();
		HashSet<StringMatch> resultSet = new HashSet<StringMatch>();
		
		for(StringMatch sm:l1.matchSet)
		{
			l1Set.add(sm.value);
		}
		for(StringMatch sm:l2.matchSet)
		{
			l2Set.add(sm.value);
		}
		l1Set.removeAll(l2Set);
		for(StringMatch sm:l1.matchSet)
		{
				if(l1Set.contains(sm.value))
					resultSet.add(sm);
		}
		diff.matchSet = resultSet;
		return diff;
	}
	
	/*public static StringMatchSet difference(StringMatchSet l1, StringMatchSet l2) {
		StringMatchSet diff = new StringMatchSet(l1);
		
		for(String key : l2.getStrings()) {
			if(diff.containsString(key)) {
				diff.removeKey(key);
			}
		}
		
		return diff;
	}
	
	public StringMatchSet difference(StringMatchSet o) {
		return StringMatchSet.difference(this, o);
	}
	
	/*public boolean put(String key, StringMatch val) {
		Set<StringMatch> smset;
		boolean existed;
		if(!(list.containsKey(key))) {
			smset = new HashSet<StringMatch>();
			existed = false;
		} else {
			smset = list.get(key);
			existed = true;
		}
		
		smset.add(val);
		return existed;
	}*/
	
	/*public void putSet(String key, Set<StringMatch> set) {
		list.put(key, set);
	}
	
	public boolean removeKey(String key) {
		Object prev = list.remove(key);
		if(prev == null) {
			return false;
		}
		return true;
	}
	
	public boolean removeStringMatch(String key, StringMatch val) {
		if(!list.containsKey(key)) {
			return false;
		}
		
		return list.get(key).remove(val);
	}

	public void clear() {
		list.clear();
	}

	public boolean containsString(String key) {
		return list.containsKey(key);
	}

	public boolean containsStringMatch(StringMatch value) {
		Collection<Set<StringMatch>> values = list.values();
		for(Set<StringMatch> stringMatchSet : values) {
			if(stringMatchSet.contains(value)) {
				return true;
			}
		}
		return false;
	}

	public Set<StringMatch> get(String key) {
		return list.get(key);
	}

	public boolean isEmpty() {
		return list.isEmpty();
	}

	public HashSet<StringMatch> getMatchSet() {
		matchSet.addAll(matchList);
		return matchSet;
	}
	public Set<String> getStrings() {
		return list.keySet();
	}

	public Collection<StringMatch> getStringMatches() {
		Collection<StringMatch> stringMatches = new ArrayList<StringMatch>();
		for(Set<StringMatch> smSet : list.values()) {
			for(StringMatch sm : smSet) {
				stringMatches.add(sm);
			}
		}
		
		return stringMatches;
	}
	*/
	
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("StringMatchSet {");
		for(StringMatch sm : matchSet) {
			sb.append(sm.toString() + ",");
		}
		
		// delete trailing ','
		if(matchSet.size() > 0) {
			sb.deleteCharAt(sb.length()-1);
		}
		
		return sb.toString();
	}
}
